const Clutter   = imports.gi.Clutter;
const Gdk       = imports.gi.Gdk;
const GtkClutter = imports.gi.GtkClutter;
const Gtk       = imports.gi.Gtk;
const Lang      = imports.lang;
const Mx        = imports.gi.Mx;
const Octopus   = imports.gi.Octopus;
const OctopusMx = imports.gi.OctopusMx;
const Signals   = imports.signals;

const AlbumArt      = imports.albumArt;
const PlaylistPanel = imports.playlistPanel;

const PANELWIDTH = 670;
const ICONSIZE = 30;
const ICONSIZE_SMALL = 20;
const TRACKLISTWIDTH = 320

function TracklistPanel (container,/*IMedialibInfo*/tracklist_model) {
	this._init (container, tracklist_model);
}

TracklistPanel.prototype = {
	_init: function (container, tracklist_model) {
		this.tracklist_model = tracklist_model;
		this.scrollActor;
		this.albumPanelArray = [];
		this.albumPanelArrayIndex = 0;
		this.tracklistPanelBackgroundStack = new Mx.Stack ({ style_class: 'tracklistPanel-background-cover',
		                                                     reactive: true }); //cover medialibPanel
		container.add_child (this.tracklistPanelBackgroundStack);

		this.tracklistPanelBackgroundClose = new Mx.Button ({ style_class: 'tracklistPanel-background-close' });
		this.tracklistPanelBackgroundClose.connect ('clicked', Lang.bind(this, function () {
			this.tracklistPanelClose ();
		}));
		this.tracklistPanelBackgroundStack.add_child (this.tracklistPanelBackgroundClose);

		this.tracklistPanelBackgroundLayout = new Mx.BoxLayout ({ orientation: Mx.Orientation.HORIZONTAL,
		                                                          x_align: Clutter.ActorAlign.END,
		                                                          spacing: 20 });
		this.tracklistPanelBackgroundStack.add_child (this.tracklistPanelBackgroundLayout);

		this.tracklistPanelStack = new Mx.Stack ({ name: 'tracklistPanel-background',
		                                           width: PANELWIDTH,
		                                           reactive: true });
		this.tracklistPanelBackgroundLayout.add_child (this.tracklistPanelStack);
		this.tracklistPanelStack.connect('button-release-event', Lang.bind(this, this.onButtonReleaseEvent));

		this.tracklistPanelPlaylistSpaceholder = new Mx.Frame ({ width: PlaylistPanel.PLAYLISTWIDTH });
		this.tracklistPanelBackgroundLayout.add_child (this.tracklistPanelPlaylistSpaceholder);

		this.tracklistPanelVBox = new Mx.BoxLayout ({ orientation: Mx.Orientation.VERTICAL,
		                                              x_align: Clutter.ActorAlign.FILL,
		                                              y_align: Clutter.ActorAlign.FILL });
		this.tracklistPanelStack.add_child (this.tracklistPanelVBox);

		if (tracklist_model instanceof Octopus.Album) {
			//artist album
			this.tracklistPanelArtist = new Mx.Label ({ style_class: 'tracklistPanel-artist' });
			this.tracklistPanelArtist.text = tracklist_model.get_artist_performer ();
			this.tracklistPanelVBox.add_child (this.tracklistPanelArtist);
			this.tracklistPanelAlbum = new Mx.Label ({ style_class: 'tracklistPanel-album' });
			this.tracklistPanelAlbum.text = tracklist_model.get_album_partofset ();
			this.tracklistPanelVBox.add_child (this.tracklistPanelAlbum);
			this.tracklistPanelLayout = new Mx.Frame ({ style_class: 'tracklistPanel-layout-album' });
			this.tracklistPanelVBox.add_child (this.tracklistPanelLayout);

			this.addSignalId =
			tracklist_model.connect ('add', Lang.bind (this, function (/*IMedialibInfo*/medialib_info, /*MedialibTracklist*/tracklist_model) {
				let album = new AlbumPanel (this.tracklistPanelLayout, /*MedialibTracklist*/tracklist_model);
				this.albumPanelArray[this.albumPanelArrayIndex++] = album;
				this.scrollActor = album.albumPanelTracklist;
			}));
			this.addFinishedSignalId =
			tracklist_model.connect ('add-finished', Lang.bind (this, function (/*IMedialibInfo*/medialib_info) {
				tracklist_model.disconnect (this.addSignalId);
				tracklist_model.disconnect (this.addFinishedSignalId);
			}));
		}

		if (   (tracklist_model instanceof Octopus.Playlist)
		    || (tracklist_model instanceof Octopus.CollectionNoGroup)
		    || (tracklist_model instanceof Octopus.CollectionGroupedByAlbum)) {
			//name
			this.tracklistPanelNameStack = new Mx.Stack ({ style_class: 'tracklistPanel-name-layout' });
			this.tracklistPanelVBox.add_child (this.tracklistPanelNameStack);
			this.tracklistPanelNameButtonLayout = new Mx.BoxLayout ({ style_class: 'tracklistPanel-name-button-layout',
			                                                          x_align: Clutter.ActorAlign.END });
			this.tracklistPanelNameStack.add_child (this.tracklistPanelNameButtonLayout);
			//name label / edit button
			this.tracklistPanelNameLabel = new Mx.Label ({ style_class: 'tracklistPanel-name-label' });
			this.tracklistPanelNameLabel.text = tracklist_model.name;
			if (   (tracklist_model instanceof Octopus.Playlist)
			    && (tracklist_model.stored_in_medialib == false) 
			    && (tracklist_model.name == "")) {
				this.tracklistPanelNameLabel.text = "new playlist";
			}
			this.tracklistPanelNameStack.add_child (this.tracklistPanelNameLabel);
			if (tracklist_model.stored_in_medialib) {
				this.tracklistPanelNameEdit = new Mx.Button ({ style_class: 'tracklistPanel-name-edit',
				                                               height: ICONSIZE, width: ICONSIZE });
			} else {
				this.tracklistPanelNameEdit = new Mx.Button ({ style_class: 'tracklistPanel-name-save-as',
				                                               height: ICONSIZE, width: ICONSIZE });
			}
			this.tracklistPanelNameButtonLayout.add_child (this.tracklistPanelNameEdit);
			this.tracklistPanelNameEdit.connect ('clicked', Lang.bind(this, function () {
				this.tracklistPanelNameLabel.visible = false;
				this.tracklistPanelNameEdit.visible = false;
				this.tracklistPanelNameGtkEntry.text = this.tracklistPanelNameLabel.text;
				this.tracklistPanelNameEntry.visible = true;
				this.tracklistPanelNameCancel.visible = true;
				this.tracklistPanelNameSave.visible = true;
			}));
			this.tracklistPanelNameEdit.connect ('enter-event', Lang.bind(this, function () {
				this.emit ('show-message-bar-text', "rename");
			}));
			this.tracklistPanelNameEdit.connect ('leave-event', Lang.bind(this, function () {
				this.emit ('show-message-bar-text', "");
			}));
			//name entry / save, cancel button
			this.tracklistPanelNameGtkEntry = new Gtk.Entry ({ name: 'tracklistPanel-name-entry' });
			this.tracklistPanelNameEntry = new GtkClutter.Actor ({ contents: this.tracklistPanelNameGtkEntry,
			                                                       margin_right: 69,
			                                                       visible: false });
			this.tracklistPanelNameStack.add_child (this.tracklistPanelNameEntry);

			this.tracklistPanelNameCancel = new Mx.Button ({ style_class: 'tracklistPanel-name-cancel',
			                                                 height: ICONSIZE,
			                                                 width: ICONSIZE,
			                                                 visible: false });
			this.tracklistPanelNameButtonLayout.add_child (this.tracklistPanelNameCancel);
			this.tracklistPanelNameCancel.connect ('clicked', Lang.bind(this, function () {
				this.tracklistPanelNameLabel.visible = true;
				this.tracklistPanelNameEdit.visible = true;
				this.tracklistPanelNameEntry.visible = false;
				this.tracklistPanelNameCancel.visible = false;
				this.tracklistPanelNameSave.visible = false;
			}));
			this.tracklistPanelNameCancel.connect ('enter-event', Lang.bind(this, function () {
				this.emit ('show-message-bar-text', "cancel");
			}));
			this.tracklistPanelNameCancel.connect ('leave-event', Lang.bind(this, function () {
				this.emit ('show-message-bar-text', "");
			}));
			this.tracklistPanelNameSave = new Mx.Button ({ style_class: 'tracklistPanel-name-save',
			                                               height: ICONSIZE,
			                                               width: ICONSIZE,
			                                               visible: false });
			this.tracklistPanelNameButtonLayout.add_child (this.tracklistPanelNameSave);
			this.tracklistPanelNameSave.connect ('clicked', Lang.bind(this, function () {
				this.tracklistPanelNameLabel.visible = true;
				this.tracklistPanelNameEdit.visible = true;
				this.tracklistPanelNameEntry.visible = false;
				this.tracklistPanelNameCancel.visible = false;
				this.tracklistPanelNameSave.visible = false;
				if (tracklist_model.stored_in_medialib) {
					let renameSignalId =
					tracklist_model.connect ('rename-finished', Lang.bind(this, function (/*Playlist/CollectionNoGroup/CollectionGroupedByAlbum*/tracklist_model, /*string*/name) {
						this.tracklistPanelNameLabel.text = name;
						tracklist_model.disconnect (renameSignalId);
					}));
					tracklist_model.xmms_collection_rename (this.tracklistPanelNameGtkEntry.text);
				} else {
					tracklist_model.xmms_collection_create (this.tracklistPanelNameGtkEntry.text);
					this.tracklistPanelNameLabel.text = this.tracklistPanelNameGtkEntry.text;
				}
			}));
			this.tracklistPanelNameSave.connect ('enter-event', Lang.bind(this, function () {
				this.emit ('show-message-bar-text', "save");
			}));
			this.tracklistPanelNameSave.connect ('leave-event', Lang.bind(this, function () {
				this.emit ('show-message-bar-text', "");
			}));

			if (tracklist_model instanceof Octopus.Playlist) {
				this.tracklistPanelLayout = new Mx.Frame ({ style_class: 'tracklistPanel-layout-playlist' });
				this.tracklistPanelVBox.add_child (this.tracklistPanelLayout);
			}
			if (   (tracklist_model instanceof Octopus.CollectionNoGroup)
			    || (tracklist_model instanceof Octopus.CollectionGroupedByAlbum)) {
				this.tracklistPanelCollectionStack = new Mx.Stack ({ x_align: Clutter.ActorAlign.FILL,
				                                                     y_align: Clutter.ActorAlign.FILL });
				this.tracklistPanelVBox.add_child (this.tracklistPanelCollectionStack);
				this.tracklistPanelScrollView = new Mx.ScrollView ();
				this.tracklistPanelCollectionStack.add_child (this.tracklistPanelScrollView);
				this.tracklistPanelLayout = new Mx.BoxLayout ({ style_class: 'tracklistPanel-layout-collection',
				                                                orientation: Mx.Orientation.VERTICAL });
				this.tracklistPanelScrollView.add_child (this.tracklistPanelLayout);
			}

			this.addSignalId =
			tracklist_model.connect ('add', Lang.bind (this, function (/*IMedialibInfo*/medialib_info, /*MedialibTracklist*/tracklist_model) {
				let tracklist = new AlbumPanel (this.tracklistPanelLayout, /*MedialibTracklist*/tracklist_model);
				this.albumPanelArray[this.albumPanelArrayIndex++] = tracklist;
				if (tracklist_model instanceof Octopus.Playlist) {
					this.scrollActor = tracklist.albumPanelTracklist;
				}
			}));
			this.addFinishedSignalId =
			tracklist_model.connect ('add-finished', Lang.bind (this, function (/*IMedialibInfo*/medialib_info) {
				tracklist_model.disconnect (this.addSignalId);
				tracklist_model.disconnect (this.addFinishedSignalId);
				if (   (tracklist_model instanceof Octopus.CollectionNoGroup)
				    || (tracklist_model instanceof Octopus.CollectionGroupedByAlbum)) {
					this.scrollActor = this.tracklistPanelLayout;
				}
			}));
		}

		this.tracklistPanelCloseButton = new Mx.Button ({ style_class: 'tracklistPanel-close',
		                                                  x_align: Clutter.ActorAlign.END,
		                                                  y_align: Clutter.ActorAlign.START,
		                                                  height: ICONSIZE,
		                                                  width: ICONSIZE });
		this.tracklistPanelCloseButton.connect ('clicked', Lang.bind(this, function () {
			this.tracklistPanelClose ();
		}));
		this.tracklistPanelStack.add_child (this.tracklistPanelCloseButton);
		this.tracklistPanelOverlay = new Mx.Frame ({ name: 'tracklistPanel-overlay' });
		this.tracklistPanelStack.add_child (this.tracklistPanelOverlay);

	},

	onButtonReleaseEvent: function (actor, event, user_data) {
		this.emit ('grab-key-focus');
	},

	onKeyPressEvent: function (/*uint*/keyval, /*string*/str, /*Gdk.ModifierType*/modifiers) {
		if (keyval == Gdk.KEY_Home) { //Home
			this.scrollActor.vertical_adjustment.value = 0;
		}
		if (keyval == Gdk.KEY_End) { //End
			this.scrollActor.vertical_adjustment.value = this.scrollActor.vertical_adjustment.upper;
		}
		if (keyval == Gdk.KEY_Page_Up) { //Page_Up
			this.scrollActor.vertical_adjustment.value =
			    this.scrollActor.vertical_adjustment.value
			  - this.scrollActor.vertical_adjustment.page_increment;
		}
		if (keyval == Gdk.KEY_Page_Down) { //Page_Down
			this.scrollActor.vertical_adjustment.value =
			    this.scrollActor.vertical_adjustment.value
			  + this.scrollActor.vertical_adjustment.page_increment;
		}
		if (keyval == Gdk.KEY_Up) { //Up
			if ((modifiers & Gdk.ModifierType.SHIFT_MASK) == Gdk.ModifierType.SHIFT_MASK) {
				this.scrollActor.add_selected_prev ();
			}
			this.scrollActor.vertical_adjustment.value =
			    this.scrollActor.vertical_adjustment.value
			  - this.scrollActor.vertical_adjustment.step_increment;
		}
		if (keyval == Gdk.KEY_Down) { //Down
			if ((modifiers & Gdk.ModifierType.SHIFT_MASK) == Gdk.ModifierType.SHIFT_MASK) {
				this.scrollActor.add_selected_next ();
			}
			this.scrollActor.vertical_adjustment.value =
			    this.scrollActor.vertical_adjustment.value
			  + this.scrollActor.vertical_adjustment.step_increment;
		}
	},

	tracklistPanelShow: function () {
		this.tracklist_model.request_data ();
		this.emit ('grab-key-focus');
	},

	tracklistPanelClose: function () {
		for (let i = 0; i < this.albumPanelArray.length; i++) {
			this.albumPanelArray[i].destroy ();
		}
		this.albumPanelArray = null;
		this.tracklistPanelBackgroundStack.destroy ();
		this.emit ('tracklist-panel-close');
	}
};

Signals.addSignalMethods(TracklistPanel.prototype);

function AlbumPanel (/*Mx.Frame*/container, /*MedialibTracklist*/tracklist_model) {
	this._init (container, tracklist_model);
}

AlbumPanel.prototype = {
	_init: function (/*Mx.Frame*/container, /*MedialibTracklist*/tracklist_model) {
		//requires: tracklist_model of type MedialibTracklist (Album, Playlist, CollectionAlbum)
		this.albumPanelAlbumartTracklistTable = new Mx.Table ({ x_align: Clutter.ActorAlign.FILL,
		                                                        y_align: Clutter.ActorAlign.FILL });
		container.add_child (this.albumPanelAlbumartTracklistTable);
		//albumart
		this.albumArtStack = new Mx.Stack ({ name: 'albumPanel-albumart-background',
		                                     y_align: Clutter.ActorAlign.START });
		this.albumPanelAlbumartTracklistTable.insert_actor (this.albumArtStack, 0, 0);
		this.albumArt = new AlbumArt.AlbumArt (this.albumArtStack,
		                                       300); //albumArtSize
		if (   (tracklist_model instanceof Octopus.Album)
		    || (tracklist_model instanceof Octopus.CollectionAlbum)) {
			this.albumArt.loadAlbumArt (/*Album/CollectionAlbum*/tracklist_model.picture_front);
			this.albumArt.defaultAlbumArtArtist.text = tracklist_model.artist;
			this.albumArt.defaultAlbumArtAlbum.text = tracklist_model.album;
		} else if (tracklist_model instanceof Octopus.CollectionNoGroup) {
			this.albumArt.defaultAlbumArtArtist.text = "Collection";
		} else if (tracklist_model instanceof Octopus.Playlist) {
			this.albumArt.defaultAlbumArtArtist.text = "Playlist";
		}
		this.albumArtOverlay = new Mx.Frame ({ name: 'albumPanel-albumart-overlay' });
		this.albumArtStack.add_child (this.albumArtOverlay);

		//tracklist
		this.albumPanelTracklistVBox = new Mx.BoxLayout ({ style_class: 'albumPanel-tracklist-vbox',
		                                                   orientation: Mx.Orientation.VERTICAL });
		this.albumPanelAlbumartTracklistTable.insert_actor (this.albumPanelTracklistVBox, 0, 1);
		this.albumPanelTracklistControl = new Mx.BoxLayout ({ style_class: 'albumPanel-control',
		                                                      orientation: Mx.Orientation.HORIZONTAL,
		                                                      x_align: Clutter.ActorAlign.END});
		this.albumPanelTracklistVBox.add_child (this.albumPanelTracklistControl);
		this.albumPanelTracklistSelectAllButton = new Mx.Button ({ style_class: 'albumPanel-tracklist-select-all',
		                                                           width: ICONSIZE_SMALL,
		                                                           height: ICONSIZE_SMALL,
		                                                           is_toggle: true });
		this.albumPanelTracklistControl.add_child (this.albumPanelTracklistSelectAllButton);
		this.albumPanelTracklistSelectAllButton.connect ('clicked', Lang.bind(this, function () {
			if (this.albumPanelTracklistSelectAllButton.toggled) {
				for (let i=0; i<this.albumPanelTracklist.get_list_size (); i++) {
					this.albumPanelTracklist.set_selected (this.albumPanelTracklist.get_track (i));
				}
			} else {
				this.albumPanelTracklist.unselect_tracklist ();
			}
		}));
		this.albumPanelTracklistAddAllButton = new Mx.Button ({ style_class: 'albumPanel-tracklist-add-all',
		                                                        width: ICONSIZE_SMALL,
		                                                        height: ICONSIZE_SMALL });
		this.albumPanelTracklistControl.add_child (this.albumPanelTracklistAddAllButton);
		this.albumPanelTracklistAddAllButton.connect ('clicked', Lang.bind(this, function () {
			for (let i=0; i<this.albumPanelTracklist.get_list_size (); i++) {
				global.get_active_playlist ().xmms_playlist_add (this.albumPanelTracklist.get_track (i).track_model.id);
			}
		}));

		if (   (tracklist_model instanceof Octopus.Album)
		    || (tracklist_model instanceof Octopus.Playlist)) {
			this.albumPanelTracklistLayout = new Mx.ScrollView ({ style_class: 'albumPanel-tracklist-scrollview',
			                                                      y_align: Clutter.ActorAlign.FILL,
			                                                      width: TRACKLISTWIDTH });
		}
		if (   (tracklist_model instanceof Octopus.CollectionAlbum)
		    || (tracklist_model instanceof Octopus.CollectionNoGroup)) {
			this.albumPanelTracklistLayout = new Mx.BoxLayout ({ style_class: 'albumPanel-tracklist-scrollview',
			                                                     y_align: Clutter.ActorAlign.FILL,
			                                                     orientation: Mx.Orientation.VERTICAL,
			                                                     width: TRACKLISTWIDTH });
		}
		this.albumPanelTracklistVBox.add_child (this.albumPanelTracklistLayout);
		this.albumPanelTracklist = new OctopusMx.MxTracklist ();
		this.albumPanelTracklist.enable_drag_action ();
		this.albumPanelTracklist.style_class = 'albumPanel-tracklist';
		this.albumPanelTracklist.orientation = Mx.Orientation.VERTICAL;
		this.albumPanelTracklistLayout.add_child (this.albumPanelTracklist);

		this.addTrackSignalId =
		tracklist_model.connect('add-track', Lang.bind (this, function (/*MedialibTracklist*/tracklist_model, /*Track*/track_model) {
			let track = new OctopusMx.MxFrameTrack ({ /*Track*/track_model: track_model,
			                                          background_style_class: "tracklistentry-background",
			                                          overlay_style_class:    "tracklistentry-overlay" });
			track.reactive = true;
			track.connect('button-release-event', Lang.bind(this, this.onTrackButtonReleaseEvent));
			let tracklistEntryContent = new TracklistEntryContent (track.get_track_content (), tracklist_model, track_model);
			let tracklistEntryMouseOverMenu = new TracklistEntryMouseOverMenu (track.get_track_mouse_over_menu (), track_model, track, this.albumPanelTracklist);
			this.albumPanelTracklist.add_track (/*MxFrameTrack*/track);
			let tracklistEntryDragHandleContent = new TracklistEntryDragHandleContent (track.get_drag_handle (), track_model);
		}));
		this.addTrackFinishedSignalId =
		tracklist_model.connect('add-track-finished', Lang.bind (this, function (/*MedialibTracklist*/tracklist_model, /*int*/trackCount) {
			if ((   (tracklist_model instanceof Octopus.Playlist)
			     || (tracklist_model instanceof Octopus.CollectionAlbum)
			     || (tracklist_model instanceof Octopus.CollectionNoGroup))) {
				this.albumArt.defaultAlbumArtAlbum.text = trackCount + " Track(s)";
			}
			tracklist_model.disconnect (this.addTrackSignalId);
			tracklist_model.disconnect (this.addTrackFinishedSignalId);
		}));
		tracklist_model.requestTracklist();
	},

	onTrackButtonReleaseEvent: function (/*MxFrameTrack*/track, /*Clutter.ButtonEvent*/event, user_data) {
		if ((event.get_button () == 1) && (event.get_click_count () == 1)) {  //left mouse button
			if ((event.get_state () & Clutter.ModifierType.CONTROL_MASK) == Clutter.ModifierType.CONTROL_MASK) {
				//toggle selected
				this.albumPanelTracklist.toggle_selected (track);
			} else if ((event.get_state () & Clutter.ModifierType.SHIFT_MASK) == Clutter.ModifierType.SHIFT_MASK) {
				//select all actors between this and the last selected actor
				this.albumPanelTracklist.multi_select (track);
			} else {
				//select one actor, unselect all others
				this.albumPanelTracklist.unselect_tracklist ();
				this.albumPanelTracklist.set_selected (track);
			}
		}
		if ((event.get_button () == 1) && (event.get_click_count () == 2)) { //double click (left)
			global.get_active_playlist ().xmms_playlist_add(track.track_model.id);
		}
		if ((event.get_button () == 3) && (event.get_click_count () == 1)) {  //right mouse button
		}
		return false; //propagate
	},

	destroy: function () {
		for (let i = 0; i < this.albumPanelTracklist.get_n_children (); i++) {
			this.albumPanelTracklist.get_child_at_index (i)/*MxFrameTrack*/.destroy ();
		}
		this.albumPanelAlbumartTracklistTable.destroy ();
	}
};

Signals.addSignalMethods(AlbumPanel.prototype);

const TRACKNRWIDTH = 40;
const ALBUMARTSIZE = 40;
const TITLEWIDTH = 215;
const DURATIONWIDTH = 45;

function TracklistEntryContent (/*Mx.Frame*/container, /*MedialibTracklist*/tracklist_model, /*Track*/track_model) {
	this._init (container, tracklist_model, track_model);
}

TracklistEntryContent.prototype = {
	_init: function (/*Mx.Frame*/ container, /*MedialibTracklist*/tracklist_model, /*Track*/track_model) {
		this.tracklistEntryLayoutBoxHorizontal = new Mx.BoxLayout ({ orientation: Mx.Orientation.HORIZONTAL });
		container.add_child (this.tracklistEntryLayoutBoxHorizontal);

		//grouped by album
		if (   (tracklist_model instanceof Octopus.Album)
		    || (tracklist_model instanceof Octopus.CollectionAlbum)) {
			this.tracklistEntryTracknr = new Mx.Label ({ style_class: 'tracklistentry-tracknr',
			                                             width: TRACKNRWIDTH });
			this.tracklistEntryLayoutBoxHorizontal.add_child (this.tracklistEntryTracknr);
			this.tracklistEntryTracknr.text = (track_model.tracknr).toString ();
		}
		//not grouped
		if (   (tracklist_model instanceof Octopus.Playlist)
		    || (tracklist_model instanceof Octopus.CollectionNoGroup)) {
			this.tracklistEntryAlbumArtStack = new Mx.Stack ({ style_class: 'tracklistentry-album-art-background',
			                                                   width: ALBUMARTSIZE,
			                                                   height: ALBUMARTSIZE });
			this.tracklistEntryLayoutBoxHorizontal.add_child (this.tracklistEntryAlbumArtStack);
			this.tracklistEntryAlbumArtContainer = new Mx.Frame ();
			this.tracklistEntryAlbumArtStack.add_child (this.tracklistEntryAlbumArtContainer);
			this.albumArt = new AlbumArt.AlbumArt (this.tracklistEntryAlbumArtContainer,
			                                       ALBUMARTSIZE); //albumArtSize
			this.albumArt.loadAlbumArt (track_model.picture_front);
			this.tracklistEntryAlbumArtOverlay = new Mx.Frame ({ style_class: 'tracklistentry-album-art-overlay' });
			this.tracklistEntryAlbumArtStack.add_child (this.tracklistEntryAlbumArtOverlay);
		}

		this.tracklistEntryTitleArtistVBox = new Mx.BoxLayout ({ orientation: Mx.Orientation.VERTICAL });
		this.tracklistEntryLayoutBoxHorizontal.add_child (this.tracklistEntryTitleArtistVBox);

		this.tracklistEntryTitle = new Mx.Label ({ style_class: 'tracklistentry-title',
		                                           width: TITLEWIDTH });
		this.tracklistEntryTitleArtistVBox.add_child (this.tracklistEntryTitle);
		this.tracklistEntryTitle.text = track_model.title;

		this.tracklistEntryArtist = new Mx.Label ({ style_class: 'tracklistentry-artist',
		                                            width: TITLEWIDTH });
		this.tracklistEntryTitleArtistVBox.add_child (this.tracklistEntryArtist);
		this.tracklistEntryArtist.text = track_model.artist;

		this.tracklistEntryDuration = new Mx.Label ({ style_class: 'tracklistentry-duration',
		                                              width: DURATIONWIDTH });
		this.tracklistEntryLayoutBoxHorizontal.add_child (this.tracklistEntryDuration);
		this.tracklistEntryDuration.text = Octopus.utils_format_duration (track_model.duration);
	}
};

const MENUICONSIZE = 15;

function TracklistEntryMouseOverMenu (/*Mx.Frame*/container, /*Track*/track_model, /*MxFrameTrack*/track, /*MxTracklist*/tracklist) {
	this._init (container, track_model, track, tracklist);
}

TracklistEntryMouseOverMenu.prototype = {
	_init: function (/*Mx.Frame*/container, /*Track*/track_model, /*MxFrameTrack*/track, /*MxTracklist*/tracklist) {
		//mouse-over-menu buttons
		this.tracklistEntryMenuLayout = new Mx.BoxLayout ({ style_class: 'tracklistentry-menu-layout',
		                                                    orientation: Mx.Orientation.HORIZONTAL,
		                                                    x_align: Clutter.ActorAlign.END,
		                                                    y_align: Clutter.ActorAlign.END });
		container.add_child (this.tracklistEntryMenuLayout);
		//append
		this.tracklistEntryMenuAppend = new Mx.Button ({ style_class: 'tracklistentry-menu-append',
		                                                 height: MENUICONSIZE,
		                                                 width: MENUICONSIZE });
		this.tracklistEntryMenuLayout.add_child (this.tracklistEntryMenuAppend);
		this.tracklistEntryMenuAppend.connect ('clicked', Lang.bind(this, function () {
			global.get_active_playlist ().xmms_playlist_add(track.track_model.id);
		}));
		//selected
		this.tracklistEntryMenuSelected = new Mx.Button ({ style_class: 'tracklistentry-menu-selected',
		                                                   height: MENUICONSIZE,
		                                                   width: MENUICONSIZE,
		                                                   is_toggle: true });
		this.tracklistEntryMenuLayout.add_child (this.tracklistEntryMenuSelected);
		this.tracklistEntryMenuSelected.connect ('clicked', Lang.bind(this, function () {
			tracklist.toggle_selected (track);
		}));
		track.connect ('notify::selected', Lang.bind(this, function () {
			if (track.selected) {
				this.tracklistEntryMenuSelected.toggled = true;
			} else {
				this.tracklistEntryMenuSelected.toggled = false;
			}
		}));
		//play
		this.tracklistEntryMenuPlay = new Mx.Button ({ style_class: 'tracklistentry-menu-play',
		                                               height: MENUICONSIZE,
		                                               width: MENUICONSIZE });
		this.tracklistEntryMenuLayout.add_child (this.tracklistEntryMenuPlay);
		this.tracklistEntryMenuPlay.connect ('clicked', Lang.bind(this, function () {
			global.get_active_playlist ().xmms_playlist_add_and_set_next(track.track_model.id);
		}));
	}
};

function TracklistEntryDragHandleContent (/*Mx.Frame*/container, /*Track*/track_model) {
	this._init (container, track_model);
}

TracklistEntryDragHandleContent.prototype = {
	_init: function (container, track_model) {
		this.dragHandleBackground = new Mx.Frame ({ style_class: 'tracklistentrydraghandle-background' });
		container.add_child (this.dragHandleBackground);

		this.dragHandleTitleArtistVBox = new Mx.BoxLayout ({ orientation: Mx.Orientation.VERTICAL });
		this.dragHandleBackground.add_child (this.dragHandleTitleArtistVBox);

		this.dragHandleTitle = new Mx.Label ({ style_class: 'tracklistentrydraghandle-title',
		                                       width: TITLEWIDTH });
		this.dragHandleTitle.text = track_model.title;
		this.dragHandleTitleArtistVBox.add_child (this.dragHandleTitle);

		this.dragHandleArtist = new Mx.Label ({ style_class: 'tracklistentrydraghandle-artist' });
		this.dragHandleArtist.text = track_model.artist;
		this.dragHandleTitleArtistVBox.add_child (this.dragHandleArtist);
	}

};
